package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }


    @Override
    public List<CategoryEntity> getCacheFromDb() throws InterruptedException {
        String JSONOBJECT = stringRedisTemplate.opsForValue().get("JSONOBJECT");
        if(StringUtils.isEmpty(JSONOBJECT)){
            System.out.println("缓存不命中将查询数据库。。。。");
            return getCacheFromDbWithRedisLock();
        }
        System.out.println("缓存命中直接返回。。。。");
        return JSON.parseObject(JSONOBJECT, new TypeReference<List<CategoryEntity>>() {});
    }


    public List<CategoryEntity> getCacheFromDbWithRedisLock() throws InterruptedException {
        PageUtils pageUtils = new PageUtils();
        pageUtils = queryPage(new HashMap<>());
        Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("JSONOBJECT",JSON.toJSONString(pageUtils.getList()),30,TimeUnit.SECONDS);
        if(lock){
            try {
                System.out.println("获取分布式锁成功。。。");
            }finally {
                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                //String script = "if redis.call('get', \"lock\") == \""+uuid+"\" then return redis.call('del', \"lock\") else return 0 end";
                Long result =  stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class),Collections.singletonList("JSONOBJECT"),JSON.toJSONString(pageUtils.getList()));
                System.out.println(result);

            }
            return (List<CategoryEntity>) pageUtils.getList();
        }else{
            System.out.println("获取分布式锁失败。。。等待重试");
            Thread.sleep(1000);
            return getCacheFromDbWithRedisLock();
        }
    }

}